/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 *
 */

import { TaskInputValue } from '@ohos/hvigor';
import fse from 'fs-extra';
import path from 'path';

import { RuntimeOnlyObj } from '../options/build/build-opt.js';
import { ModuleTargetData } from '../tasks/data/hap-task-target-data.js';

import { OhosLogger } from './log/ohos-logger.js';
import { isSubset } from './array-util.js';
import { CustomTypesConst } from '../const/common-const.js';

/**
 * 生成buildProfile.ets文件
 *
 * @param buildProfileData
 * @param targetData
 * @param _log
 */
export const normalizedFileData = (buildProfileData: object, targetData: ModuleTargetData, _log: OhosLogger): string => {
  const resStr = `${generateConstVariable(buildProfileData, targetData, _log)}\n${generateExportClass(buildProfileData)}`;
  return resStr;
};

export const generateConstVariable = (buildProfileData: object, targetData: ModuleTargetData, _log: OhosLogger): string => {
  const commentsStr = '/**\n * Use these variables when you tailor your ArkTS code. They must be of the const type.\n */\n';
  const itemStr = 'export const ';
  let resStr = commentsStr;

  Object.keys(buildProfileData).forEach((key) => {
    const val = buildProfileData[key as keyof object];
    if (typeof val === 'string') {
      resStr += `${itemStr + key} = '${val}';\n`;
    } else if (typeof val === 'number' || typeof val === 'boolean') {
      resStr += `${itemStr + key} = ${val};\n`;
    } else {
      _log.printErrorExit('BUILDPROFILEFIELDS_ONLY_SUPPORT_NUMBER_STRING_BOOLEAN', [typeof val, val, targetData.getModuleModel().getProfilePath()]);
    }
  });
  return resStr;
};

export const generateExportClass = (buildProfileData: object): string => {
  const commentsStr = '/**\n * BuildProfile Class is used only for compatibility purposes.\n */\n';
  const firstStr = 'export default class BuildProfile { \n';
  const itemStr = 'static readonly ';
  let resStr = commentsStr + firstStr;
  Object.keys(buildProfileData).forEach((key) => {
    resStr += `\t${itemStr + key} = ${key};\n`;
  });
  resStr += '}';
  return resStr;
};

export const getRuntimeOnlyObjMap = (
  modulePath: string,
  runtimeOnlyObj: RuntimeOnlyObj | undefined,
  unionDependencyList: any[],
  suffix?: number | string,
): Map<string, TaskInputValue> => {
  const map = new Map<string, TaskInputValue>();
  if (!runtimeOnlyObj) {
    return map;
  }
  if (runtimeOnlyObj.sources) {
    runtimeOnlyObj.sources.forEach((relativePath) => {
      const absolutePath = path.resolve(modulePath, relativePath);
      if (fse.existsSync(absolutePath)) {
        map.set(relativePath, absolutePath);
      }
    });
  }
  if (runtimeOnlyObj.packages) {
    if (isSubset(unionDependencyList, runtimeOnlyObj.packages)) {
      map.set(`runtimeOnlyPackages${suffix ?? ''}`, runtimeOnlyObj.packages);
    }
  }
  return map;
};

export const getCustomTypePathIfExists = (modulePath: string, type: string): string | undefined => {
  const typePath = path.isAbsolute(type) ? type : path.resolve(modulePath, type);
  for (const suffix of CustomTypesConst.CUSTOM_TYPES_SUFFIX) {
    const filePath = `${typePath}${suffix}`;
    if (fse.existsSync(`${typePath}${suffix}`)) {
      return filePath;
    }
  }
  for (const index of CustomTypesConst.CUSTOM_TYPES_INDEX) {
    const filePath = path.resolve(typePath, index);
    if (fse.existsSync(filePath)) {
      return filePath;
    }
  }
  return undefined;
}
